/**
 * @Title wheel-utils系统
 * @Package com.senyint.sys.utils
 * @Description 工具
 * @Company 心医国际数字医疗系统（大连） 有限公司
 * @Copyright (c) 2016, 2017, Senyint. All rights reserved.
 * @date 2017年12月7日 下午5:27:01 
 * @author WangNaiFei
 * @version 1.0
 */

package com.senyint.sys.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * {@code DateUtil}
 * 
 * @Description: TODO
 *               <p>
 * @author WangNaiFei,WangNaiFei@senyint.com
 * @date 2017年12月20日 上午11:58:08
 * @version 1.0
 * @since jdk1.7+
 */
public class DateUtil {

	public static final String FORMAT_DEFAULT = "yyyy-MM-dd HH:mm:ss";
	public static final String FORMAT_DEFAULT_WITH_MILLISECOND = "yyyy-MM-dd HH:mm:ss.SSS";
	public static final String FORMAT_DEFAULT_NO_TIME = "yyyy-MM-dd";

	/**
	 * 日期所在当年的起止时间
	 * 
	 * @see 不带时间
	 * @param cal
	 * @return
	 */
	public static Calendar[] getThisYearStartEnd(Calendar cal) {
		Calendar start = (Calendar) cal.clone();

		// 一月为0
		start.set(Calendar.MONTH, 0);

		start.set(Calendar.DAY_OF_MONTH, 1);

		toDayStartTime(start);

		Calendar end = (Calendar) start.clone();
		end.add(Calendar.YEAR, 1);

		return new Calendar[] { start, end };
	}

	/**
	 * 日期所在当月的起止时间
	 * 
	 * @see 不带时间
	 * @param cal
	 * @return
	 */
	public static Calendar[] getThisMonthStartEnd(Calendar cal) {
		Calendar start = (Calendar) cal.clone();

		start.set(Calendar.DAY_OF_MONTH, 1);

		toDayStartTime(start);

		Calendar end = (Calendar) start.clone();
		end.add(Calendar.MONTH, 1);

		return new Calendar[] { start, end };
	}

	/**
	 * 日期所在一周的起止时间
	 * 
	 * @see 不带时间
	 * @param cal
	 * @return
	 */
	public static Calendar[] getThisWeekStartEnd(Calendar cal) {
		Calendar start = (Calendar) cal.clone();
		// 设置为周一
		start.set(Calendar.DATE, Calendar.MONDAY);

		toDayStartTime(start);

		Calendar end = (Calendar) start.clone();
		// 周一加一周
		end.add(Calendar.WEEK_OF_MONTH, 1);

		return new Calendar[] { start, end };
	}

	/**
	 * 日期当天的起止时间
	 * 
	 * @see 不带时间
	 * @param cal
	 * @return
	 */
	public static Calendar[] getThisDayStartEnd(Calendar cal) {
		Calendar start = (Calendar) cal.clone();

		toDayStartTime(start);

		Calendar end = (Calendar) start.clone();
		end.add(Calendar.DAY_OF_MONTH, 1);

		return new Calendar[] { start, end };
	}

	/**
	 * 日期一年前
	 * 
	 * @see 带时间
	 * @param cal
	 * @return
	 */
	public static Calendar[] getTillYearStartEnd(Calendar cal) {
		Calendar end = (Calendar) cal.clone();
		Calendar start = (Calendar) end.clone();
		start.add(Calendar.YEAR, -1);
		return new Calendar[] { start, end };
	}

	/**
	 * 日期一月前
	 * 
	 * @see 带时间
	 * @param cal
	 * @return
	 */
	public static Calendar[] getTillMonthStartEnd(Calendar cal) {
		Calendar end = (Calendar) cal.clone();
		Calendar start = (Calendar) end.clone();
		start.set(Calendar.MONTH, -1);
		return new Calendar[] { start, end };
	}

	/**
	 * 日期一周前
	 * 
	 * @see 带时间
	 * @param cal
	 * @return
	 */
	public static Calendar[] getTillWeekStartEnd(Calendar cal) {
		Calendar end = (Calendar) cal.clone();
		Calendar start = (Calendar) end.clone();
		start.set(Calendar.WEEK_OF_YEAR, -1);
		return new Calendar[] { start, end };
	}

	/**
	 * 日期一天前
	 * 
	 * @see 带时间
	 * @param cal
	 * @return
	 */
	public static Calendar[] getTillDayStartEnd(Calendar cal) {
		Calendar end = (Calendar) cal.clone();
		Calendar start = (Calendar) end.clone();
		start.set(Calendar.DAY_OF_MONTH, -1);
		return new Calendar[] { start, end };
	}

	/**
	 * 设置时间为当天最开始
	 * 
	 * @param calendar
	 * @return
	 */
	public static Calendar toDayStartTime(Calendar calendar) {
		calendar.set(Calendar.HOUR, 0);
		calendar.set(Calendar.AM_PM, Calendar.AM);// hourofday没hour优先级高？
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar;
	}

	/**
	 * 设置时间为当天最后一秒
	 * 
	 * @param calendar
	 * @return
	 */
	@Deprecated
	public static Calendar toDayEndTime(Calendar calendar) {
		calendar.set(Calendar.HOUR, 23);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.SECOND, 59);
		calendar.set(Calendar.MILLISECOND, 999);
		return calendar;
	}

	/**
	 * 根据生日计算属相
	 * 
	 * @param birthday
	 * @return
	 */
	public static int getAnimalsign(Date birthday) {
		Calendar b = Calendar.getInstance();
		b.setTime(birthday);
		return getAnimalsign(b.get(Calendar.YEAR));
	}

	/**
	 * 根据年份计算属相
	 * 
	 * @param yearofbirthday
	 * @return
	 */
	public static int getAnimalsign(int yearofbirthday) {
		int start = 1901;
		int id = 0;
		int x = (start - yearofbirthday) % 12;
		if ((x == 1) || (x == -11)) {
			id = 1;
		} else if (x == 0) {
			id = 2;
		} else if ((x == 11) || (x == -1)) {
			id = 3;
		} else if ((x == 10) || (x == -2)) {
			id = 4;
		} else if ((x == 9) || (x == -3)) {
			id = 5;
		} else if ((x == 8) || (x == -4)) {
			id = 6;
		} else if ((x == 7) || (x == -5)) {
			id = 7;
		} else if ((x == 6) || (x == -6)) {
			id = 8;
		} else if ((x == 5) || (x == -7)) {
			id = 9;
		} else if ((x == 4) || (x == -8)) {
			id = 10;
		} else if ((x == 3) || (x == -9)) {
			id = 11;
		} else if ((x == 2) || (x == -10)) {
			id = 12;
		}
		return id;
	}

	/**
	 * 根据生日计算星座
	 * 
	 * @param birthday
	 * @return 12星座
	 */
	public static int getConstellation(Date birthday) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(birthday);
		return getConstellation(cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH));
	}

	/**
	 * 根据月份和日期判断星座
	 * 
	 * @param month
	 * @param day
	 * @return 12星座
	 */
	public static int getConstellation(int month, int day) {
		int id = 0;
		if (((month == 1) && (day >= 20)) || ((month == 2) && (day <= 18))) {
			id = 11;
		} else if (((month == 2) && (day >= 19)) || ((month == 3) && (day <= 20))) {
			id = 12;
		} else if (((month == 3) && (day >= 21)) || ((month == 4) && (day <= 19))) {
			id = 1;
		} else if (((month == 4) && (day >= 20)) || ((month == 5) && (day <= 20))) {
			id = 2;
		} else if (((month == 5) && (day >= 21)) || ((month == 6) && (day <= 21))) {
			id = 3;
		} else if (((month == 6) && (day >= 22)) || ((month == 7) && (day <= 22))) {
			id = 4;
		} else if (((month == 7) && (day >= 23)) || ((month == 8) && (day <= 22))) {
			id = 5;
		} else if (((month == 8) && (day >= 23)) || ((month == 9) && (day <= 22))) {
			id = 6;
		} else if (((month == 9) && (day >= 23)) || ((month == 10) && (day <= 22))) {
			id = 7;
		} else if (((month == 10) && (day >= 23)) || ((month == 11) && (day <= 21))) {
			id = 8;
		} else if (((month == 11) && (day >= 22)) || ((month == 12) && (day <= 21))) {
			id = 9;
		} else if (((month == 12) && (day >= 22)) || ((month == 1) && (day <= 19))) {
			id = 10;
		}
		return id;
	}

	/**
	 * 日期转时间
	 * 
	 * @see SimpleDateFormat 多线程处理有问题，如多线程使用必须采用每次现实例化的方式
	 * @param date
	 * @param format
	 * @return
	 */
	public static String dateToStr(Date date, String format) {
		return new SimpleDateFormat(format).format(date);
	}

	/**
	 * 按照yyyy-MM-dd HH:mm:ss的格式，日期转字符串
	 * 
	 * @param date
	 * @return yyyy-MM-dd HH:mm:ss
	 */
	public static String dateToStr(Date date) {
		return dateToStr(date, "yyyy-MM-dd HH:mm:ss");
	}

	/**
	 * 字符转日期
	 * 
	 * @see SimpleDateFormat 多线程处理有问题，如多线程使用必须采用每次现实例化的方式
	 * @param dateStr
	 * @param format
	 * @return
	 * @throws ParseException
	 */
	public static Date strToDate(String dateStr, String format) throws ParseException {
		return new SimpleDateFormat(format).parse(dateStr);
	}

	/**
	 * 按照yyyy-MM-dd HH:mm:ss的格式，字符串转日期
	 * <p>
	 * 
	 * @author NaiFei Wang, wangnaifei@senyint.com
	 * @date 2016年3月31日 上午10:47:22
	 * @version 1.0
	 * @param dateStr
	 * @return
	 * @throws ParseException
	 */
	public static Date strToDate(String dateStr) throws ParseException {
		return strToDate(dateStr, "yyyy-MM-dd HH:mm:ss");
	}

	/**
	 * 秒转天小时分秒
	 * 
	 * @param seconds
	 * @return
	 */
	public static String secondsToString(long seconds) {
		String[] units = { "秒", "分", "小时", "天" };
		int[] rate = { 60, 60, 24 };
		int i = 0;
		int l = rate.length;
		String result = "";
		long s = seconds;
		while ((s > 0L) && (i < l)) {
			long t = s % rate[i];
			if (t > 0L) {
				result = String.valueOf(t) + units[i] + result;
			}
			s /= rate[i];
			i++;
			if ((i == l) && (s > 0L)) {
				result = String.valueOf(s) + units[i] + result;
			}
		}
		return result;
	}

	/**
	 * 获取到目前为止的时间差
	 * 
	 * @param date
	 * @return x年x月x日x小时x分
	 */
	public static int[] getDateDiffAll(Date date) {
		Calendar now = Calendar.getInstance();
		Calendar birthdayc = Calendar.getInstance();
		birthdayc.setTime(date);
		int y = 0;
		int M = 0;
		int d = 0;
		int H = 0;
		int m = 0;

		while (now.after(birthdayc)) {
			y++;
			birthdayc.add(1, 1);
		}

		y--;
		birthdayc.add(1, -1);

		while (now.after(birthdayc)) {
			M++;
			birthdayc.add(2, 1);
		}

		M--;
		birthdayc.add(2, -1);

		while (now.after(birthdayc)) {
			d++;
			birthdayc.add(5, 1);
		}

		d--;
		birthdayc.add(5, -1);

		while (now.after(birthdayc)) {
			H++;
			birthdayc.add(11, 1);
		}

		H--;
		birthdayc.add(11, -1);

		while (now.after(birthdayc)) {
			m++;
			birthdayc.add(12, 1);
		}

		m--;

		int[] raturn = { y, M, d, H, m };
		return raturn;
	}

	/**
	 * 生日转年龄 (一个单位)
	 * 
	 * @param birthday
	 * @return
	 */
	public static int[] getAge(Date birthday) {
		int[] ageAll = getDateDiffAll(birthday);
		int[] r = new int[2];
		for (int age : ageAll) {
			if (age > 0) {
				r[0] = age;
				break;
			}
			r[1] += 1;
		}
		return r;
	}

	/**
	 * 年纪单位
	 * 
	 * @param unit
	 * @return
	 */
	public static String getAgeUnit(int unit) {
		String[] units = { "岁", "月", "天", "小时", "分" };
		return units[unit];
	}

	/**
	 * 判断当前日期是星期几
	 * 
	 * @param pTime 修要判断的时间
	 * @return dayForWeek 判断结果
	 * @Exception 发生异常
	 */
	public static int dayForWeek(String pTime) throws Exception {
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		Calendar c = Calendar.getInstance();
		c.setTime(format.parse(pTime));
		int dayForWeek = 0;
		if (c.get(Calendar.DAY_OF_WEEK) == 1) {
			dayForWeek = 7;
		} else {
			dayForWeek = c.get(Calendar.DAY_OF_WEEK) - 1;
		}
		return dayForWeek;
	}

	/**
	 * 获取指定日期的当月天数
	 */
	public static int theLastDayInMonth(Date date) {
		Calendar a = Calendar.getInstance();
		a.setTime(date);
		int maxDate = a.getActualMaximum(Calendar.DATE);
		return maxDate;
	}

	/**
	 * 日期计算的方法
	 * 
	 * @param date 传入的日期
	 * @param type 加减的类型 如:Calendar.DAY_OF_MONTH 日
	 * @param num 加减的数量 +5：5 -5
	 * @return
	 */
	public static Date addDate(Date date, int type, int num) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(type, num);
		return c.getTime();
	}

	/**
	 * @Title: setTime
	 * @Description: TODO
	 * @author WangNaifei,WangNaifei@senyint.com
	 * @date 2018年5月25日 下午12:09:23
	 * @version 1.0
	 * @param HHmmss format HH:mm:ss
	 * @return
	 * @return
	 */
	public static Calendar setTime(Calendar cal, String timesNoDate) {
		if (StringUtils.isEmpty(timesNoDate)) {
			throw new IllegalArgumentException("timesNoDate is empty");
		}
		String[] split = timesNoDate.split(":");
		if (split.length == 3) {
			cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(split[0]));
			cal.set(Calendar.MINUTE, Integer.parseInt(split[1]));
			cal.set(Calendar.SECOND, Integer.parseInt(split[2]));
		} else {
			throw new IllegalArgumentException("timesNoDate mast like HH:mm:ss but " + timesNoDate);
		}
		return cal;
	}
}